﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Face_Recognition
{
    public class Cluster
    {
        List<Hole> holes = new List<Hole>();

        Point center;

        Rectangle boundingBox;

        public Rectangle AreaBox
        {
            get { return new Rectangle(boundingBox.X * Morphology.ShrinkValue, boundingBox.Y * Morphology.ShrinkValue, boundingBox.Width * Morphology.ShrinkValue, boundingBox.Height * Morphology.ShrinkValue); }
        }

        public Rectangle BoundingBox
        {
            get { return boundingBox; }
            set { boundingBox = value; }
        }

        int holesCount;
        float value;

        public List<Hole> Holes
        {
            get { return holes; }
            set { holes = value; }
        }

        public Cluster()
        {

        }

        public void AddHole(Hole hole)
        {
            holes.Add(hole);
        }

        public bool ContainsHole(Hole hole)
        {
            return holes.Contains(hole);
        }

        public void CalculateCenter()
        {
            int x=0, y=0;

            foreach (Hole h in holes)
            {
                x += h.Center.X;
                y += h.Center.Y;
            }

            center.X = x / holes.Count;
            center.Y = y / holes.Count;
        }

        public bool CheckDownApex(bool[,] skinMask)
        {
            this.CalculateCenter();

            CalculateValue();

            if (!(((float)boundingBox.Width / (float)boundingBox.Height) > 0.5 && ((float)boundingBox.Width / (float)boundingBox.Height) < 1.5))
                return false;

            if (boundingBox.Width * boundingBox.Height < 2 * holesCount)
                return false;

            short count=0;
            float skinPixelsCount=0;

          

            for (int w = this.AreaBox.X; w < this.AreaBox.Width + this.AreaBox.X - 1; w++)
            {
                for (int h = this.AreaBox.Y; h < this.AreaBox.Height + this.AreaBox.Y - 1; h++)
                {
                    if (h < skinMask.GetLength(0) && w < skinMask.GetLength(1) && skinMask[h, w])
                        skinPixelsCount++;
                }
            }

            if (skinPixelsCount / (boundingBox.Width * boundingBox.Height) < 0.5)
                return false;
            else
                this.value = skinPixelsCount / (boundingBox.Width * boundingBox.Height);

            int eyeSize=0;
            foreach (Hole h in holes)
            {
                if (h.Center.Y < center.Y)
                {
                    if (count == 0)
                        eyeSize = h.Coordinates.Count;
                    else if (h.Coordinates.Count / eyeSize < 0.75 || h.Coordinates.Count / eyeSize > 1.25)
                        return false;

                    count++;
                }
            }

            if (count >= 2) //should be 2
                return true;
            else
                return false;
        }

        public float CalculateValue()
        {
            int count = 0;
            foreach (Hole h in holes)
            {
                count += h.Coordinates.Count;
            }
            value = count;
            holesCount = count;
            return count;
        }

        public Rectangle BoundCluster()
        {
            int xmin, xmax, ymin, ymax;
            int[] point = new int[2];
            int[] oldPoint = new int[2];
            point = new int[2] { this.Holes[0].Center.X, this.Holes[0].Center.Y };
            xmin = point[0];
            xmax = point[0];
            ymin = point[1];
            ymax = point[1];

            foreach (Hole h in this.Holes)
            {
                //while (holes.Count > 0)
                {
                    point = new int[2] { h.Center.X, h.Center.Y };
                    if (point[0] > xmax)
                        xmax = point[0];
                    if (point[0] < xmin)
                        xmin = point[0];
                    if (point[1] > ymax)
                        ymax = point[1];
                    if (point[1] < ymin)
                        ymin = point[1];
                }
            }

            BoundingBox = new Rectangle(xmin,ymin,(xmax - xmin),(ymax - ymin));

            return new Rectangle(xmin, ymin,(xmax - xmin), (ymax - ymin));
        }

        public bool Intersects(Cluster cluster)
        {
            return this.BoundingBox.IntersectsWith(cluster.BoundingBox);
        }

        public Cluster ChooseFitter(Cluster cluster)
        {
            if (this.value > cluster.value)
                return this;
            else
                return cluster;
        }

        public bool IsFitter(Cluster cluster)
        {
            if (this.CalculateValue() > cluster.CalculateValue())
                return true;
            else
                return false;
        }
    }
}
